#pragma once
#include "PixelShader.h"
#include "VertexShader.h"
#include "ComputeShader.h"
#include "Material.h"
#include "Mesh.h"
#include "ICamera.h"
#include "VertexInputLayout.h"
#include "SubModelMesh.h"
#include "Texture2D.h"

namespace Graphics{
	enum RenderState{RS_DEPTH_WRITE};
	class RenderContext;

	class MaterialManager : public Core::MemTrack{
	public:
		MaterialManager();

		virtual void initialize(RenderContext* renderContext) = 0;

		MaterialPtr getMaterialByName(std::string &name);
		MaterialPtr getMaterial(unsigned int id);

		int getVertexShaderIdByName(std::string &name);
		int getPixelShaderIdByName(std::string &name);

		int	getInputLayoutId(std::string &comparator);

		unsigned int addMaterial(MaterialPtr material);
		void removeMaterial(unsigned int id);
		unsigned int addPixelShader(PixelShaderPtr shader);
		void removePixelShader(unsigned int id);
		unsigned int addVertexShader(VertexShaderPtr shader);
		void removeVertexShader(unsigned int id);
		unsigned int addComputeShader(ComputeShaderPtr shader);
		void removeComputeShader(unsigned int id);
		unsigned int addInputLayout(VertexInputLayoutPtr layout);
		void removeInputLayout(unsigned int id);
		unsigned int addTexture2D(Texture2DPtr texture);
		void removeTexture2D(unsigned int id);

		virtual void setMaterial(unsigned int id);
		virtual void setPixelShader(unsigned int id);
		virtual void setVertexShader(unsigned int id);
		virtual void setComputeShader(unsigned int id);

		virtual void setDepthStencil(bool enable) = 0;
		virtual void setInstanceShaderVariables(MeshPtr mesh) = 0;
		virtual void setJointFrame(std::vector<Utility::Math::Matrix<4,4>> &joints, int controllerId) = 0;
		virtual void setSharedShaderVariables(ICameraPtr camera) = 0;
	protected:
		std::map<std::string,unsigned int> m_materialNameToIdMap;

		std::map<unsigned int,MaterialPtr> m_materials;
		std::map<unsigned int,PixelShaderPtr> m_pixelShaders;
		std::map<unsigned int,VertexShaderPtr> m_vertexShaders;
		std::map<unsigned int,ComputeShaderPtr> m_computeShaders;
		std::map<unsigned int,VertexInputLayoutPtr> m_inputLayouts;
		std::map<unsigned int,Texture2DPtr> m_2DTextures;

		std::map<std::string,unsigned int> m_inputLayoutTracker;
		std::map<std::string,unsigned int> m_vertexShaderNameMap;
		std::map<std::string,unsigned int> m_pixelShaderNameMap;

		int	m_activeMaterial,
			m_activePixelShader,
			m_activeVertexShader,
			m_activeComputeShader,
			m_activeInputLayout;

		unsigned int 	m_materialId,
						m_pixelShaderId,
						m_vertexShaderId,
						m_computeShaderId,
						m_inputLayoutId,
						m_2DTextureId;

		RenderContext *m_renderContext;
	};
}